# -*- coding: utf-8 -*-
from argparse import ArgumentParser

from datetime import date, timedelta

DATES_OF_MONTH = 365 / 12

argumentParser = ArgumentParser('用等额本金或等额本息两种方式计算利息')
argumentParser.add_argument('-t', '--total', type=int, help='借款总额')
argumentParser.add_argument('-d', '--dd', help='借款日期')
argumentParser.add_argument('-p', '--period', type=int, help='分期数目')
argumentParser.add_argument('-r', '--rates', type=float, help='年利率')
argumentParser.add_argument('-k', '--kind', help='还款方式，等额本金（DEBJ），等额本息（DEBX）')

args = argumentParser.parse_args()

total = args.total
dd =  date.fromisoformat(args.dd).replace(day=1)
period = args.period
rates = args.rates
kind = args.kind

def debj(total, dd, period, rates):
    """
    从借款人的角度来计算：当月还剩多少借款，当月该产生多少利息
    """
    bj = total / period

    total_d = 0
    total_r = 0

    def rev(i):
        nonlocal total_d, total_r, dd
        if i > period:
            return

        money = total -( i - 1 ) * bj
        r = ( money / 100 ) * DATES_OF_MONTH * rates / 365
        total_d += bj
        total_r += r
        # print(i, int(money), int(bj), int(r))
        # print('%s, %d, %d, %d, %d, %s, %d, %d' % (i, money, bj, r, bj+r, dd := get_next_month(dd), total_d, total_r))    # 输出用于excel分析
        print('期数：%s, 剩余借款：%d, 应还本金：%d, 应还利息：%d, 应还总额：%d, 日期：%s, 已还本金：%d, 已还利息：%d' % (i, money, bj, r, bj+r, dd := get_next_month(dd), total_d, total_r))    # 用于控制台分析

        rev(i+1)
    
    rev(1)
    print('采用等额本金的方式借款 %d 元，利率 %s ，分 %d 期， 总利息： %d' % ( total, rates, period, int(total_r)))

def debx(total, dd, period, rates):
    """
    还是从借款人的角度计算：当月还剩多少借款，当月该产生多少利息
    只不过比等额本金复杂的地方在于，提前不知道每月该还多少，需要统筹计算后，再平摊
    期数    剩余借款    应还本金    应还利息    当期总额
    1         y(1)       b(1)     y(1)*M*R     A
    2         y(2)       b(2)     y(2)*M*R     A
    3         y(3)       b(3)     y(3)*M*R     A
    4         y(4)       b(4)     y(4)*M*R     A
    .............................................
    n         y(n)       b(n)     y(n)*M*R     A

    相邻两期的剩余借款有如下关系：y(n+1) = y(n) - (A-y(n)*M*R)  --> y(n+1) = y(n)*(1+MR) - A

    y(1) = T
    y(2) = y(1)*P-A = T*P-A
    y(3) = y(2)*P-A = TP^2 - A(P+1)
    y(4) = y(3)*P-A = TP^3 - A(((P+1)*P)+1)
    y(5) = y(4)*P-A = TP^4 - A((((P+1)*P)+1)*P+1)
    ...

    可以根据如下规律先计算出每月应还总额 A。结束条件为，假设总期数为12期，则第13期剩余借款为0。
    y(13) := TP^12 - A*q = 0
    """
    T = total
    P = 1 + DATES_OF_MONTH * rates / 100 / 365

    def getA():
        if period == 1:
            return T * P

        def q(n):
            if n == 2:
                return 1
            return q(n-1) * P + 1

        return T * P ** period / q(period + 1)

    A = getA()

    total_dn = 0
    total_rn = 0

    def y(n):
        nonlocal total_dn, total_rn, dd
        if n == 1:
            return T
        
        yn1 = y(n-1)
        rn1 = yn1 * DATES_OF_MONTH * rates / 100 / 365
        dn1 = A - rn1

        total_dn += dn1
        total_rn += rn1

        # print('%s, %d, %d, %d, %d, %s, %d, %d' % (n-1, yn1, dn1, rn1, A, dd := get_next_month(dd), total_dn, total_rn))    # 输出用于excel分析
        print('期数：%s, 剩余借款：%d, 应还本金：%d, 应还利息：%d, 应还总额：%d, 日期：%s, 已还本金：%d, 已还利息：%d' % (n-1, yn1, dn1, rn1, A, dd := get_next_month(dd), total_dn, total_rn))    # 用于控制台分析

        return yn1 * P - A

    y(period + 1)

    print('采用等额息的方式借款 %d 元，利率 %s ，分 %d 期， 总利息： %d' % ( total, rates, period, total_rn))

def get_next_month(day1):
    day1 += timedelta(days=45)
    return day1.replace(day=1)

def run(total, dd, period, rates, kind):
    if kind == 'DEBJ':
        return debj(total, dd, period, rates)
    elif kind == 'DEBX':
        return debx(total, dd, period, rates)

if __name__ == '__main__':
    # total = 700000
    # dd = date.fromisoformat('2018-05-01').replace(day=1)
    # period = 360
    # rates = 3.25
    # kind = 'DEBX'
    # run(total=total, dd=dd, period=period, rates=rates, kind=kind)
    run(total, dd, period, rates, kind)
